/**
 * Java8专门的重构规则和策略定义
 * 基于你的个人偏好：文件500行+、方法80行+自动重构，遵循单一职责原则
 */

export interface RefactorRule {
  id: string;
  name: string;
  description: string;
  category: 'size' | 'java8' | 'spring' | 'architecture' | 'quality';
  priority: 'high' | 'medium' | 'low';
  autoApply: boolean;
  condition: (context: CodeAnalysisContext) => boolean;
  action: RefactorAction;
}

export interface CodeAnalysisContext {
  filePath: string;
  content: string;
  lineCount: number;
  className?: string;
  methods: MethodInfo[];
  imports: string[];
  annotations: string[];
  isSpringBootProject: boolean;
}

export interface MethodInfo {
  name: string;
  lineCount: number;
  startLine: number;
  endLine: number;
  parameters: string[];
  returnType: string;
  annotations: string[];
  complexity: number; // 圈复杂度
}

export interface RefactorAction {
  type: 'split_file' | 'split_method' | 'extract_interface' | 'java8_optimize' | 'remove_unused' | 'spring_refactor';
  description: string;
  implementation: string;
  estimatedEffort: 'low' | 'medium' | 'high';
  riskLevel: 'low' | 'medium' | 'high';
  preview?: string;
}

export class Java8RefactorRules {
  private static readonly DEFAULT_MAX_FILE_LINES = 500;
  private static readonly DEFAULT_MAX_METHOD_LINES = 80;
  private static readonly DEFAULT_MAX_METHODS_PER_CLASS = 15;
  private static readonly DEFAULT_MAX_PARAMETERS = 5;

  /**
   * 获取所有Java8重构规则
   */
  static getAllRules(): RefactorRule[] {
    return [
      ...this.getSizeRules(),
      ...this.getJava8Rules(),
      ...this.getSpringBootRules(),
      ...this.getArchitectureRules(),
      ...this.getQualityRules()
    ];
  }

  /**
   * 代码大小相关规则
   */
  private static getSizeRules(): RefactorRule[] {
    return [
      {
        id: 'large-file-split',
        name: '大文件拆分',
        description: `文件超过${this.DEFAULT_MAX_FILE_LINES}行需要拆分`,
        category: 'size',
        priority: 'high',
        autoApply: true,
        condition: (context) => context.lineCount > this.DEFAULT_MAX_FILE_LINES,
        action: {
          type: 'split_file',
          description: '将大文件按职责拆分为多个小文件',
          implementation: '基于类的职责和业务逻辑进行拆分',
          estimatedEffort: 'high',
          riskLevel: 'medium',
          preview: '建议拆分策略：1)提取内部类 2)按功能模块分离 3)提取工具方法'
        }
      },
      {
        id: 'large-method-split',
        name: '大方法拆分',
        description: `方法超过${this.DEFAULT_MAX_METHOD_LINES}行需要拆分`,
        category: 'size',
        priority: 'high',
        autoApply: true,
        condition: (context) => context.methods.some(m => m.lineCount > this.DEFAULT_MAX_METHOD_LINES),
        action: {
          type: 'split_method',
          description: '将大方法拆分为多个职责单一的小方法',
          implementation: '提取子方法，保持方法的单一职责',
          estimatedEffort: 'medium',
          riskLevel: 'low',
          preview: '建议拆分策略：1)提取验证逻辑 2)提取计算逻辑 3)提取数据处理逻辑'
        }
      },
      {
        id: 'too-many-methods',
        name: '类方法过多',
        description: `类方法超过${this.DEFAULT_MAX_METHODS_PER_CLASS}个，违反单一职责原则`,
        category: 'size',
        priority: 'medium',
        autoApply: false,
        condition: (context) => context.methods.length > this.DEFAULT_MAX_METHODS_PER_CLASS,
        action: {
          type: 'split_file',
          description: '按业务职责将类拆分为多个类',
          implementation: '分析方法的业务关联性，提取相关方法到新类',
          estimatedEffort: 'high',
          riskLevel: 'medium'
        }
      },
      {
        id: 'too-many-parameters',
        name: '方法参数过多',
        description: `方法参数超过${this.DEFAULT_MAX_PARAMETERS}个`,
        category: 'size',
        priority: 'medium',
        autoApply: false,
        condition: (context) => context.methods.some(m => m.parameters.length > this.DEFAULT_MAX_PARAMETERS),
        action: {
          type: 'java8_optimize',
          description: '使用Builder模式或参数对象封装多个参数',
          implementation: '创建参数对象或使用Java8的Builder模式',
          estimatedEffort: 'medium',
          riskLevel: 'low'
        }
      }
    ];
  }

  /**
   * Java8特性优化规则
   */
  private static getJava8Rules(): RefactorRule[] {
    return [
      {
        id: 'for-loop-to-stream',
        name: 'for循环转Stream',
        description: '传统for循环可以使用Stream API简化',
        category: 'java8',
        priority: 'medium',
        autoApply: false,
        condition: (context) => this.hasForLoopPattern(context.content),
        action: {
          type: 'java8_optimize',
          description: '使用Stream API替换传统循环',
          implementation: 'list.stream().filter().map().collect()',
          estimatedEffort: 'low',
          riskLevel: 'low',
          preview: '// 替换前: for(Item item : items) { if(item.isValid()) result.add(item.getName()); }\n// 替换后: items.stream().filter(Item::isValid).map(Item::getName).collect(Collectors.toList())'
        }
      },
      {
        id: 'null-check-to-optional',
        name: 'null检查转Optional',
        description: 'null检查可以使用Optional避免空指针异常',
        category: 'java8',
        priority: 'medium',
        autoApply: false,
        condition: (context) => this.hasNullCheckPattern(context.content),
        action: {
          type: 'java8_optimize',
          description: '使用Optional处理可能为null的值',
          implementation: 'Optional.ofNullable(value).map().orElse()',
          estimatedEffort: 'low',
          riskLevel: 'low',
          preview: '// 替换前: if(user != null && user.getName() != null) { return user.getName(); }\n// 替换后: return Optional.ofNullable(user).map(User::getName).orElse("")'
        }
      },
      {
        id: 'anonymous-to-lambda',
        name: '匿名类转Lambda',
        description: '匿名内部类可以使用Lambda表达式简化',
        category: 'java8',
        priority: 'low',
        autoApply: false,
        condition: (context) => this.hasAnonymousClassPattern(context.content),
        action: {
          type: 'java8_optimize',
          description: '使用Lambda表达式替换匿名类',
          implementation: '(param) -> expression',
          estimatedEffort: 'low',
          riskLevel: 'low',
          preview: '// 替换前: new Comparator<String>() { public int compare(String a, String b) { return a.compareTo(b); } }\n// 替换后: (a, b) -> a.compareTo(b) 或 String::compareTo'
        }
      },
      {
        id: 'method-reference',
        name: '方法引用优化',
        description: 'Lambda表达式可以使用方法引用进一步简化',
        category: 'java8',
        priority: 'low',
        autoApply: false,
        condition: (context) => this.hasMethodReferenceOpportunity(context.content),
        action: {
          type: 'java8_optimize',
          description: '使用方法引用替换Lambda表达式',
          implementation: 'Class::method',
          estimatedEffort: 'low',
          riskLevel: 'low',
          preview: '// 替换前: .map(s -> s.toUpperCase())\n// 替换后: .map(String::toUpperCase)'
        }
      },
      {
        id: 'use-parallel-stream',
        name: '并行Stream优化',
        description: '大数据量处理可以考虑使用并行Stream',
        category: 'java8',
        priority: 'low',
        autoApply: false,
        condition: (context) => this.hasLargeDataProcessing(context.content),
        action: {
          type: 'java8_optimize',
          description: '对大数据量使用parallelStream()提升性能',
          implementation: 'list.parallelStream()',
          estimatedEffort: 'low',
          riskLevel: 'medium',
          preview: '// 注意：只在数据量大且CPU密集型操作时使用parallelStream()'
        }
      }
    ];
  }

  /**
   * SpringBoot特定规则
   */
  private static getSpringBootRules(): RefactorRule[] {
    return [
      {
        id: 'controller-direct-repository',
        name: 'Controller直接访问Repository',
        description: 'Controller层不应直接访问Repository，应通过Service层',
        category: 'spring',
        priority: 'high',
        autoApply: false,
        condition: (context) => this.hasControllerRepositoryViolation(context),
        action: {
          type: 'spring_refactor',
          description: '在Controller和Repository之间添加Service层',
          implementation: '创建Service接口和实现类',
          estimatedEffort: 'medium',
          riskLevel: 'low'
        }
      },
      {
        id: 'service-transaction',
        name: 'Service方法缺少事务注解',
        description: 'Service层的数据操作方法应添加@Transactional注解',
        category: 'spring',
        priority: 'medium',
        autoApply: false,
        condition: (context) => this.needsTransactionAnnotation(context),
        action: {
          type: 'spring_refactor',
          description: '为Service层数据操作方法添加@Transactional注解',
          implementation: '@Transactional(rollbackFor = Exception.class)',
          estimatedEffort: 'low',
          riskLevel: 'low'
        }
      },
      {
        id: 'autowired-constructor',
        name: '使用构造器注入',
        description: '推荐使用构造器注入替代@Autowired字段注入',
        category: 'spring',
        priority: 'medium',
        autoApply: false,
        condition: (context) => this.hasFieldInjection(context.content),
        action: {
          type: 'spring_refactor',
          description: '使用构造器注入替代字段注入',
          implementation: '将@Autowired字段转为final字段并添加构造器',
          estimatedEffort: 'medium',
          riskLevel: 'low'
        }
      }
    ];
  }

  /**
   * 架构相关规则
   */
  private static getArchitectureRules(): RefactorRule[] {
    return [
      {
        id: 'single-responsibility-violation',
        name: '单一职责原则违反',
        description: '类承担了多个职责，需要拆分',
        category: 'architecture',
        priority: 'high',
        autoApply: false,
        condition: (context) => this.violatesSingleResponsibility(context),
        action: {
          type: 'split_file',
          description: '按职责将类拆分为多个专门的类',
          implementation: '分析类的职责，提取独立的业务逻辑到新类',
          estimatedEffort: 'high',
          riskLevel: 'medium'
        }
      },
      {
        id: 'extract-interface',
        name: '提取接口',
        description: '具体实现类应提取接口以提高可测试性',
        category: 'architecture',
        priority: 'medium',
        autoApply: false,
        condition: (context) => this.shouldExtractInterface(context),
        action: {
          type: 'extract_interface',
          description: '为Service类提取接口',
          implementation: '创建接口并让实现类实现该接口',
          estimatedEffort: 'low',
          riskLevel: 'low'
        }
      }
    ];
  }

  /**
   * 代码质量相关规则
   */
  private static getQualityRules(): RefactorRule[] {
    return [
      {
        id: 'remove-unused-imports',
        name: '清理无用导入',
        description: '删除未使用的import语句',
        category: 'quality',
        priority: 'low',
        autoApply: true,
        condition: (context) => this.hasUnusedImports(context),
        action: {
          type: 'remove_unused',
          description: '自动删除未使用的import语句',
          implementation: '分析代码使用情况，删除无用导入',
          estimatedEffort: 'low',
          riskLevel: 'low'
        }
      },
      {
        id: 'remove-unused-methods',
        name: '清理无用私有方法',
        description: '删除未被调用的私有方法',
        category: 'quality',
        priority: 'low',
        autoApply: false,
        condition: (context) => this.hasUnusedPrivateMethods(context),
        action: {
          type: 'remove_unused',
          description: '删除未被使用的私有方法',
          implementation: '分析方法调用关系，删除无用私有方法',
          estimatedEffort: 'low',
          riskLevel: 'low'
        }
      },
      {
        id: 'add-missing-javadoc',
        name: '添加JavaDoc注释',
        description: '公共方法缺少JavaDoc注释',
        category: 'quality',
        priority: 'low',
        autoApply: false,
        condition: (context) => this.missingJavaDoc(context),
        action: {
          type: 'java8_optimize',
          description: '为公共方法添加JavaDoc注释',
          implementation: '/**\n * 方法描述\n * @param param 参数描述\n * @return 返回值描述\n */',
          estimatedEffort: 'low',
          riskLevel: 'low'
        }
      }
    ];
  }

  // 辅助方法：模式检测
  private static hasForLoopPattern(content: string): boolean {
    return /for\s*\([^)]*:\s*[^)]*\)\s*\{/.test(content) && 
           (content.includes('.add(') || content.includes('result') || content.includes('collect'));
  }

  private static hasNullCheckPattern(content: string): boolean {
    return /!=\s*null|==\s*null/.test(content);
  }

  private static hasAnonymousClassPattern(content: string): boolean {
    return /new\s+\w+\s*\(\s*\)\s*\{/.test(content);
  }

  private static hasMethodReferenceOpportunity(content: string): boolean {
    return /\.\w+\([\w\s]*->\s*[\w\s]*\.\w+\(\s*\)\s*\)/.test(content);
  }

  private static hasLargeDataProcessing(content: string): boolean {
    return content.includes('stream()') && 
           (content.includes('size() >') || content.includes('length >') || content.includes('count'));
  }

  private static hasControllerRepositoryViolation(context: CodeAnalysisContext): boolean {
    return (context.content.includes('@Controller') || context.content.includes('@RestController')) &&
           context.content.includes('@Autowired') &&
           /Repository|Dao/.test(context.content);
  }

  private static needsTransactionAnnotation(context: CodeAnalysisContext): boolean {
    return context.content.includes('@Service') &&
           (context.content.includes('save(') || context.content.includes('delete(') || context.content.includes('update(')) &&
           !context.content.includes('@Transactional');
  }

  private static hasFieldInjection(content: string): boolean {
    return /@Autowired\s+private/.test(content);
  }

  private static violatesSingleResponsibility(context: CodeAnalysisContext): boolean {
    // 简化检测：方法过多或包含多种不相关的操作
    const businessMethods = context.methods.filter(m => 
      !m.name.startsWith('get') && !m.name.startsWith('set')
    ).length;
    
    return businessMethods > 8 || 
           (context.content.includes('database') && context.content.includes('email') && context.content.includes('validation'));
  }

  private static shouldExtractInterface(context: CodeAnalysisContext): boolean {
    return context.content.includes('@Service') && 
           !context.content.includes('implements') &&
           context.methods.filter(m => m.name.startsWith('public')).length > 3;
  }

  private static hasUnusedImports(context: CodeAnalysisContext): boolean {
    return context.imports.some(imp => {
      const className = imp.split('.').pop();
      return className && !context.content.includes(className);
    });
  }

  private static hasUnusedPrivateMethods(context: CodeAnalysisContext): boolean {
    return context.methods.some(method => 
      method.name.includes('private') && 
      !context.content.split(method.name)[1]?.includes(method.name + '(')
    );
  }

  private static missingJavaDoc(context: CodeAnalysisContext): boolean {
    const publicMethods = context.methods.filter(m => m.name.includes('public'));
    return publicMethods.some(method => {
      const methodIndex = context.content.indexOf(method.name);
      const beforeMethod = context.content.substring(0, methodIndex);
      return !beforeMethod.includes('/**');
    });
  }

  /**
   * 根据上下文获取适用的规则
   */
  static getApplicableRules(context: CodeAnalysisContext): RefactorRule[] {
    return this.getAllRules().filter(rule => rule.condition(context));
  }

  /**
   * 获取自动应用的规则
   */
  static getAutoApplyRules(context: CodeAnalysisContext): RefactorRule[] {
    return this.getApplicableRules(context).filter(rule => rule.autoApply);
  }

  /**
   * 按优先级排序规则
   */
  static sortByPriority(rules: RefactorRule[]): RefactorRule[] {
    const priorityOrder = { 'high': 0, 'medium': 1, 'low': 2 };
    return rules.sort((a, b) => priorityOrder[a.priority] - priorityOrder[b.priority]);
  }
}